package cn.wsalix.admin.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.anlaser.service.impl.RelatedServiceImpl;
import cn.anlaser.utils.SearchFilter;
import cn.anlaser.utils.SearchFilter.Operator;
import cn.wsalix.admin.entity.SysRole;
import cn.wsalix.admin.entity.SysUser;
import cn.wsalix.admin.entity.UserRole;
import cn.wsalix.admin.form.UserForm;
import cn.wsalix.admin.form.UserRoleForm;
import cn.wsalix.admin.repository.UserRoleRepository;
import cn.wsalix.admin.service.RoleService;
import cn.wsalix.admin.service.UserRoleService;
import cn.wsalix.admin.service.UserService;
import cn.wsalix.observable.service.RegisterService;
import cn.wsalix.observable.service.UserInfoUpService;

@Service("userRoleService")
public class UserRoleServiceImpl
		extends
		RelatedServiceImpl<UserRoleForm, UserRoleRepository, UserRole, SysUser, SysRole>
		implements UserRoleService {
	@Autowired
	private UserService userService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private UserRoleRepository userRoleRepository;

	@Override
	public SysUser findPreFix(Long preFixId) {
		return userService.findById(preFixId);
	}

	@Override
	public SysRole findPostFix(Long postFixId) {
		return roleService.findById(postFixId);
	}

	@CacheEvict(value = "myMenuCache", key = "#form.getId()")
	@Transactional
	@Override
	public void removeRelated(UserRoleForm form) {
		if (form.getId() != null) {
			userRoleRepository.delete(form.getId());
		} else {
			List<UserRole> userRoles = findByForm(form);
			userRoleRepository.delete(userRoles);
		}
	}

	/*
	 * @Override public UserRole setRelated(UserRoleForm form) {
	 * form.setUser(findPreFix(form.getPreFixId()));
	 * form.setRole(findPostFix(form.getPostFixId())); return
	 * super.setRelated(form); }
	 */
	@Transactional
	@Override
	public UserRole setRelated(UserRoleForm form) {
		userService.updateUserRole(form.getUserId());
		return super.setRelated(form);
	}

	@Override
	public List<UserRole> findRelateds(UserRoleForm form) {
		if (form.getUserId() != null && form.getUserId() != 0) {
			return userRoleRepository.findByUserId(form.getUserId());
		}
		if (form.getRoleId() != null && form.getRoleId() != 0) {
			return userRoleRepository.findByRoleId(form.getRoleId());
		}
		return null;
	}

	@Override
	public List<SysUser> findUnPreFix(Long roleId) {
		return userService.findUnUsersByRoleId(roleId);
	}

	@Override
	public List<SysRole> findUnPostFix(Long userId) {
		return roleService.findUnRolesByUserId(userId);
	}

	@Override
	public UserRoleRepository getRepository() {
		return userRoleRepository;
	}

	@Override
	public Map<String, SearchFilter> buildByForm(UserRoleForm form) {
		Map<String, Object> searchParams = new HashMap<String, Object>();
		Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
		if (form.getRoleId() != null && form.getRoleId() != 0) {
			filters.put("postFix.id", new SearchFilter("postFix.id",
					Operator.EQ, form.getRoleId()));
		}
		if (form.getUserId() != null && form.getUserId() != 0) {
			filters.put("preFix.id", new SearchFilter("preFix.id", Operator.EQ,
					form.getUserId()));
		}
		return filters;
	}

	@Override
	public String module() {
		return "/admin/user_role";
	}

	@Override
	public Class<UserRole> getEntityClazz() {
		return UserRole.class;
	}

	@Transactional
	public void insertRole(Long userId, SysRole role) {
		UserRoleForm userRoleForm = new UserRoleForm();
		userRoleForm.setUserId(userId);
		userRoleForm.setRoleId(role.getId());
		setRelated(userRoleForm);
	}

	/**
	 * @param userId
	 * @param role
	 *            删除当前用户角色
	 */
	@Transactional
	public void delCurrRole(Long userId, SysRole role) {
		if (role == null) {
			return;
		}
		UserRoleForm userRoleForm = new UserRoleForm();
		userRoleForm.setUserId(userId);
		userRoleForm.setRoleId(role.getId());
		removeRelated(userRoleForm);
	}

	@Override
	public void upUserRole(Long roleId) {
		List<SysUser> users = userService.findUsersByRoleId(roleId);
		for (SysUser user : users) {
			userService.updateUserRole(user.getId());
		}
	}

	@Override
	public List<SysRole> findUnRolesByMenuId(Long menuId) {
		return roleService.findUnRolesByMenuId(menuId);
	}

	@Transactional
	@Override
	public void update(Observable o, Object arg) {
		if (o instanceof RegisterService) {
			RegisterService userRegisterService = (RegisterService) o;
			if (arg instanceof UserForm) {
				UserForm userForm = (UserForm) arg;
				SysUser user = userRegisterService.getUser();
				if (userForm.getRole() != null
						&& userForm.getRole().getId() != null) {
					insertRole(userRegisterService.getUser().getId(),
							userForm.getRole());
				}
			}
		}
		if (o instanceof UserInfoUpService) {
			UserInfoUpService userInfoUpService = (UserInfoUpService) o;
			if (arg instanceof UserForm) {
				UserForm userForm = (UserForm) arg;
				SysUser user = userInfoUpService.getUser();
				switch (userForm.getChange()) {
				case add:
					break;
				case delete:
					break;
				case edit:
					break;
				case focus:

					break;
				case friend:

					break;
				case role:
					SysRole oldRole = userForm.getRole();
					SysRole role = userForm.getRole();
					List<UserRole> users = userRoleRepository.findUserAndRole(
							user.getId(), oldRole.getId());
					if (!users.isEmpty()) {
						if (users.size() == 1) {
							UserRole userRole = users.get(0);
							userRole.setPostFix(role);
							edit(userRole);
						} else {
							UserRole userRole = users.get(0);
							for (UserRole obj : users) {
								if (obj.getId() != userRole.getId()) {
									userRoleRepository.delete(obj);
								}
							}
							userRole.setPostFix(role);
							edit(userRole);
						}
					} else {
						UserRoleForm userRoleForm = new UserRoleForm();
						userRoleForm.setUserId(user.getId());
						userRoleForm.setRoleId(role.getId());
						setRelated(userRoleForm);
					}
					break;
				default:
					break;
				}
			}

		}
	}

	@Override
	public List<SysRole> findRolesByUserId(Long userId) {
		return userRoleRepository.findRolesByUserId(userId);
	}

	@Override
	public List<SysRole> findRolesByUsername(String username) {
		return userRoleRepository.findRolesByUserName(username);
	}

	@Override
	public List<SysRole> findAllRoles() {
		return roleService.findAll();
	}
}
